import popuplib2

__all__ = ["RaceGroup", "raceGroups"]

class RaceGroup(object):
    """
    This manages all the groups for race objects. This allows us to manage
    groups of races which means we can sort our races in the menu into nice
    grouped ordered menus.
    """
    def __init__(self, groupName, authorization=None, parent=None):
        """
        Default constructor. This initialises the group objects and ensures
        that we assign containers to manage all sub groups / races.

        @param str groupName The name of this group
        """
        from wcs.libs.races.groups.popups import RaceGroupPopup
        
        self.authorization = authorization
        self.groupName = groupName
        self.groups = {}
        self.raceOrder = []
        self.parent = parent
        self.popup = RaceGroupPopup(self).popup

    def __del__(self):
        """
        Executed when this object is destoryed. Destory all child groups and
        unload any races this group has loaded.
        """
        from wcs.libs.races import races
        
        self.groups.clear()
        for race in raceOrder:
            races.unloadRace(race)
        
    def __contains__(self, raceName):
        """
        Executed when we need to see if a group name or a race name exists
        within this current group.

        @param str raceName The group or race name to test for containment
        @return bool Whether or not the race name / race group is in 
        """
        return (raceName in self.raceOrder or raceName in self.groups)
    
    def __iter__(self):
        """
        Executed when we iterate through this object. Assume that we first want
        to iterate throught the current race group objects and then iterate
        through the race objects themselves.

        @return generator A generator containing all the groups / races this
                          group contains.
        """
        for raceGroupObject in sorted(self.groups):
            yield self.groups[raceGroupObject]
        for race in self.raceOrder:
            yield race

    def __getitem__(self, raceGroupName):
        """
        Executed when item lookup is used on this object. Assume we want to
        get the group object.

        @param str raceGroupName The name of the group that we want to retrieve
        @return RaceGroup The group object returned by the name
        """
        if raceGroupName in self.groups:
            return self.groups[raceGroupName]
        return None

    def __delitem__(self, raceGroupName):
        """
        Remove a group object from this group object.

        @param str raceGroupName The name of the group to remove
        """
        if raceGroupName in self.groups:
            del self.groups[raceGroupName]

    def __float__(self):
        """
        Returns an average to the minimum level of all the levels / groups
        within this group.

        @return float The average minimum levels of all races inside this group
        """
        from wcs.libs.races import races
        
        allMaxLevels = 0
        amountOfRaces = 0
        for group in self.groups:
            allMaxLevels += float(self.groups[group])
            amountOfRaces += 1
        for race in self.raceOrder:
            allMaxLevels += races[race].minLevel
            amountOfRaces += 1
        if not amountOfRaces or not allMaxLevels:
            return 0.0
        return float(allMaxLevels) / amountOfRaces

    def sortGroups(self, firstKey, secondKey):
        """
        Sorts groups based on the average level of the groups, followed by
        the groups name (alpha) order.

        @param str firstKey The name of the first group to test
        @param str secondKey The name of the second group to test
        @return int The order that the firstKey is to the secondkey:
                        o -1 if firstKey has a higher order than secondKey
                        o 0  if firstKey has an even order than secondKey
                        o 1  if firstKey has a lower order than secondKey
        """
        firstValue = float(self.groups[firstKey])
        secondValue = float(self.groups[secondKey])
        if firstValue < secondValue:
            return -1
        if firstValue < secondValue:
            return 1
        return {True: -1, False: 1}[firstKey < secondKey]

    @staticmethod
    def sortRaces(firstKey, secondKey):
        """
        Sorts races based on the minimum level required to play them followed by
        the name (alpha) order.

        @param str firstKey The name of the first race to test
        @param str secondKey The name of the second race to test
        @return int The order that the firstKey is to the secondkey:
                        o -1 if firstKey has a higher order than secondKey
                        o 0  if firstKey has an even order than secondKey
                        o 1  if firstKey has a lower order than secondKey
        """
        from wcs.libs.races import races
        
        raceOne = races[firstKey]
        raceTwo = races[secondKey]
        if raceOne.minLevel < raceTwo.minLevel:
            return -1
        if raceOne.minLevel > raceTwo.minLevel:
            return 1
        return {True: -1, False: 1}[firstKey < secondKey]

    def addGroup(self, groupName):
        """
        Adds a group object to this. Since groups may contain an infinite subset
        of groups, this allows us to ensure that maximum recurssion is allowed.

        @param str groupName The name of the group to add as a child group
        """
        self.groups[groupName] = RaceGroup(groupName, parent=self)
        return self.groups[groupName]
        
raceGroups = RaceGroup("_main_unordered")